home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
gnu
/
gnpltsrc.lha
/
util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-22
|
24KB
|
1,101 lines
#ifndef lint
static char *RCSid = "$Id: util.c,v 1.33 1995/12/07 21:41:12 drd Exp $";
#endif
/* GNUPLOT - util.c */
/*
* Copyright (C) 1986 - 1993 Thomas Williams, Colin Kelley
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the modified code. Modifications are to be distributed
* as patches to released version.
*
* This software is provided "as is" without express or implied warranty.
*
*
* AUTHORS
*
* Original Software:
* Thomas Williams, Colin Kelley.
*
* Gnuplot 2.0 additions:
* Russell Lang, Dave Kotz, John Campbell.
*
* Gnuplot 3.0 additions:
* Gershon Elber and many others.
*
*/
#include <ctype.h>
#include <math.h> /* get prototype for sqrt */
#include "plot.h"
#include "setshow.h" /* for month names etc */
TBOOLEAN screen_ok;
/* TRUE if command just typed; becomes FALSE whenever we
send some other output to screen. If FALSE, the command line
will be echoed to the screen before the ^ error message. */
static char *num_to_str __P((double r));
static void parse_esc __P((char *instr));
static char * read_int __P((char *s, int nr, int *d));
/*
* chr_in_str() compares the characters in the string of token number t_num
* with c, and returns TRUE if a match was found.
*/
#ifdef ANSI_C
int chr_in_str(int t_num, char c)
#else
int chr_in_str(t_num, c)
int t_num;
char c;
#endif
{
register int i;
if (!token[t_num].is_token)
return(FALSE); /* must be a value--can't be equal */
for (i = 0; i < token[t_num].length; i++) {
if (input_line[token[t_num].start_index+i] == c)
return(TRUE);
}
return FALSE;
}
/*
* equals() compares string value of token number t_num with str[], and
* returns TRUE if they are identical.
*/
int equals(t_num, str)
int t_num;
char *str;
{
register int i;
if (!token[t_num].is_token)
return(FALSE); /* must be a value--can't be equal */
for (i = 0; i < token[t_num].length; i++) {
if (input_line[token[t_num].start_index+i] != str[i])
return(FALSE);
}
/* now return TRUE if at end of str[], FALSE if not */
return(str[i] == '\0');
}
/*
* almost_equals() compares string value of token number t_num with str[], and
* returns TRUE if they are identical up to the first $ in str[].
*/
int almost_equals(t_num, str)
int t_num;
char *str;
{
register int i;
register int after = 0;
register start = token[t_num].start_index;
register length = token[t_num].length;
if (!token[t_num].is_token)
return(FALSE); /* must be a value--can't be equal */
for (i = 0; i < length + after; i++) {
if (str[i] != input_line[start + i]) {
if (str[i] != '$')
return(FALSE);
else {
after = 1;
start--; /* back up token ptr */
}
}
}
/* i now beyond end of token string */
return(after || str[i] == '$' || str[i] == '\0');
}
int isstring(t_num)
int t_num;
{
return(token[t_num].is_token &&
(input_line[token[t_num].start_index] == '\'' ||
input_line[token[t_num].start_index] == '\"'));
}
int isanumber(t_num)
int t_num;
{
return(!token[t_num].is_token);
}
int isletter(t_num)
int t_num;
{
return(token[t_num].is_token &&
((isalpha(input_line[token[t_num].start_index]))||
(input_line[token[t_num].start_index] == '_')));
}
/*
* is_definition() returns TRUE if the next tokens are of the form
* identifier =
* -or-
* identifier ( identifer {,identifier} ) =
*/
int is_definition(t_num)
int t_num;
{
/* variable? */
if(isletter(t_num) && equals(t_num+1,"="))
return 1;
/* function? */
/* look for dummy variables */
if(isletter(t_num) && equals(t_num+1,"(") && isletter(t_num+2)) {
t_num += 3; /* point past first dummy */
while(equals(t_num,",")) {
if(!isletter(++t_num))
return 0;
t_num += 1;
}
return(equals(t_num,")") && equals(t_num+1,"="));
}
/* neither */
return 0;
}
/*
* copy_str() copies the string in token number t_num into str, appending
* a null. No more than max chars are copied (including \0).
*/
void copy_str(str, t_num, max)
char str[];
int t_num;
int max;
{
register int i = 0;
register int start = token[t_num].start_index;
register int count;
if ((count = token[t_num].length) >= max) {
count = max-1;
#ifdef DEBUG_STR
fprintf(stderr, "str buffer overflow in copy_str");
#endif
}
do {
str[i++] = input_line[start++];
} while (i != count);
str[i] = '\0';
}
/* length of token string */
int token_len(t_num)
int t_num;
{
return (token[t_num].length);
}
/*
* quote_str() does the same thing as copy_str, except it ignores the
* quotes at both ends. This seems redundant, but is done for
* efficency.
*/
void quote_str(str, t_num, max)
char str[];
int t_num;
int max;
{
register int i = 0;
register int start = token[t_num].start_index + 1;
register int count;
if ((count = token[t_num].length - 2) >= max) {
count = max-1;
#ifdef DEBUG_STR
fprintf(stderr, "str buffer overflow in quote_str");
#endif
}
if (count>0) {
do {
str[i++] = input_line[start++];
} while (i != count);
}
str[i] = '\0';
/* convert \t and \nnn (octal) to char if in double quotes */
if ( input_line[token[t_num].start_index] == '"' )
parse_esc(str);
}
/*
* capture() copies into str[] the part of input_line[] which lies between
* the begining of token[start] and end of token[end].
*/
void capture(str,start,end,max)
char str[];
int start,end;
int max;
{
register int i,e;
e = token[end].start_index + token[end].length;
if(e-token[start].start_index>=max) {
e=token[start].start_index+max-1;
#ifdef DEBUG_STR
fprintf(stderr, "str buffer overflow in capture");
#endif
}
for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
*str++ = input_line[i];
*str = '\0';
}
/*
* m_capture() is similar to capture(), but it mallocs storage for the
* string.
*/
void m_capture(str,start,end)
char **str;
int start,end;
{
register int i,e;
register char *s;
if (*str) /* previous pointer to malloc'd memory there */
free(*str);
e = token[end].start_index + token[end].length;
*str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
s = *str;
for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
*s++ = input_line[i];
*s = '\0';
}
/*
* m_quote_capture() is similar to m_capture(), but it removes
quotes from either end if the string.
*/
void m_quote_capture(str,start,end)
char **str;
int start,end;
{
register int i,e;
register char *s;
if (*str) /* previous pointer to malloc'd memory there */
free(*str);
e = token[end].start_index + token[end].length-1;
*str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
s = *str;
for (i = token[start].start_index + 1; i < e && input_line[i] != '\0'; i++)
*s++ = input_line[i];
*s = '\0';
}
void convert(val_ptr, t_num)
struct value *val_ptr;
int t_num;
{
*val_ptr = token[t_num].l_val;
}
static char *num_to_str(r)
double r;
{
static i = 0;
static char s[4][25];
int j = i++;
if ( i > 3 ) i = 0;
sprintf( s[j], "%.15g", r );
if ( strchr( s[j], '.' ) == NULL &&
strchr( s[j], 'e' ) == NULL &&
strchr( s[j], 'E' ) == NULL )
strcat( s[j], ".0" );
return s[j];
}
void disp_value(fp,val)
FILE *fp;
struct value *val;
{
switch(val->type) {
case INTGR:
fprintf(fp,"%d",val->v.int_val);
break;
case CMPLX:
if (val->v.cmplx_val.imag != 0.0 )
fprintf(fp,"{%s, %s}",
num_to_str(val->v.cmplx_val.real),
num_to_str(val->v.cmplx_val.imag));
else
fprintf(fp,"%s",
num_to_str(val->v.cmplx_val.real));
break;
default:
int_error("unknown type in disp_value()",NO_CARET);
}
}
double
real(val) /* returns the real part of val */
struct value *val;
{
switch(val->type) {
case INTGR:
return((double) val->v.int_val);
case CMPLX:
return(val->v.cmplx_val.real);
}
int_error("unknown type in real()",NO_CARET);
/* NOTREACHED */
return((double)0.0);
}
double
imag(val) /* returns the imag part of val */
struct value *val;
{
switch(val->type) {
case INTGR:
return(0.0);
case CMPLX:
return(val->v.cmplx_val.imag);
}
int_error("unknown type in imag()",NO_CARET);
/* NOTREACHED */
return((double)0.0);
}
double
magnitude(val) /* returns the magnitude of val */
struct value *val;
{
switch(val->type) {
case INTGR:
return((double) abs(val->v.int_val));
case CMPLX:
return(sqrt(val->v.cmplx_val.real*
val->v.cmplx_val.real +
val->v.cmplx_val.imag*
val->v.cmplx_val.imag));
}
int_error("unknown type in magnitude()",NO_CARET);
/* NOTREACHED */
return((double)0.0);
}
double
angle(val) /* returns the angle of val */
struct value *val;
{
switch(val->type) {
case INTGR:
return((val->v.int_val >= 0) ? 0.0 : Pi);
case CMPLX:
if (val->v.cmplx_val.imag == 0.0) {
if (val->v.cmplx_val.real >= 0.0)
return(0.0);
else
return(Pi);
}
return(atan2(val->v.cmplx_val.imag,
val->v.cmplx_val.real));
}
int_error("unknown type in angle()",NO_CARET);
/* NOTREACHED */
return((double)0.0);
}
struct value *
Gcomplex(a,realpart,imagpart)
struct value *a;
double realpart, imagpart;
{
a->type = CMPLX;
a->v.cmplx_val.real = realpart;
a->v.cmplx_val.imag = imagpart;
return(a);
}
struct value *
Ginteger(a,i)
struct value *a;
int i;
{
a->type = INTGR;
a->v.int_val = i;
return(a);
}
#if !defined(vms) && !defined(HAVE_STRERROR)
/* substitute for systems that don't have ANSI function strerror */
extern int sys_nerr;
extern char *sys_errlist[];
char *strerror(no)
int no;
{
static char res_str[30];
if(no>sys_nerr) {
sprintf(res_str, "unknown errno %d", no);
return res_str;
} else {
return sys_errlist[no];
}
}
#endif
void os_error(str,t_num)
char str[];
int t_num;
{
#ifdef vms
static status[2] = {1, 0}; /* 1 is count of error msgs */
#endif
register int i;
/* reprint line if screen has been written to */
if (t_num != NO_CARET) { /* put caret under error */
if (!screen_ok)
fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
for (i = 0; i < token[t_num].start_index; i++) {
(void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
}
(void) putc('^',stderr);
(void) putc('\n',stderr);
}
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
fprintf(stderr,"%s\n",str);
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
if (!interactive)
if (infile_name != NULL)
fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
else
fprintf(stderr,"line %d: ", inline_num);
#ifdef vms
status[1] = vaxc$errno;
sys$putmsg(status);
(void) putc('\n',stderr);
#else /* vms */
fprintf(stderr,"(%s)\n\n", strerror(errno));
#endif /* vms */
longjmp(env, TRUE); /* bail out to command line */
}
void int_error(str,t_num)
char str[];
int t_num;
{
register int i;
/* reprint line if screen has been written to */
if (t_num != NO_CARET) { /* put caret under error */
if (!screen_ok)
fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
for (i = 0; i < token[t_num].start_index; i++) {
(void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
}
(void) putc('^',stderr);
(void) putc('\n',stderr);
}
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
if (!interactive)
if (infile_name != NULL)
fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
else
fprintf(stderr,"line %d: ", inline_num);
fprintf(stderr,"%s\n\n", str);
longjmp(env, TRUE); /* bail out to command line */
}
void int_warn(str,t_num)
char str[];
int t_num;
{
register int i;
/* Warn without bailing out to command line. Not a user error */
/* reprint line if screen has been written to */
if (t_num != NO_CARET) { /* put caret under error */
if (!screen_ok)
fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
for (i = 0; i < token[t_num].start_index; i++) {
(void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
}
(void) putc('^',stderr);
(void) putc('\n',stderr);
}
for (i = 0; i < sizeof(PROMPT) - 1; i++)
(void) putc(' ',stderr);
if (!interactive)
if (infile_name != NULL)
fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
else
fprintf(stderr,"line %d: ", inline_num);
fprintf(stderr,"warning: %s\n", str);
} /* int_warn */
/* Lower-case the given string (DFK) */
/* Done in place. */
void
lower_case(s)
char *s;
{
register char *p = s;
while (*p != '\0') {
if (isupper(*p))
*p = tolower(*p);
p++;
}
}
/* Squash spaces in the given string (DFK) */
/* That is, reduce all multiple white-space chars to single spaces */
/* Done in place. */
void
squash_spaces(s)
char *s;
{
register char *r = s; /* reading point */
register char *w = s; /* writing point */
TBOOLEAN space = FALSE; /* TRUE if we've already copied a space */
for (w = r = s; *r != '\0'; r++) {
if (isspace(*r)) {
/* white space; only copy if we haven't just copied a space */
if (!space) {
space = TRUE;
*w++ = ' ';
} /* else ignore multiple spaces */
} else {
/* non-space character; copy it and clear flag */
*w++ = *r;
space = FALSE;
}
}
*w = '\0'; /* null terminate string */
}
static int mndday[12] = { 31,28,31,30,31,30,31,31,30,31,30,31};
/* days in year */
int
gdysize(yr)
int yr;
{
if (!(yr%4)) {
if ((!(yr%100)) && yr%400)
return(365);
return(366);
}
return(365);
}
/* new strptime() and gmtime() to allow time to be read as 24 hour,
* and spaces in the format string. time is converted to seconds from
* year 2000.... */
char *
gstrptime(s,fmt,tm)
char *s;
char *fmt;
struct tm *tm;
{
int yday, date;
date = yday = 0;
tm->tm_mday = 0;
tm->tm_mon = tm->tm_year = tm->tm_yday = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
while ( *fmt != '\0' ) {
while(*s == *fmt) {s++; fmt++;}
if ( *fmt != '%' )
break;
fmt++;
if ( *fmt == 'd' ) { /* read a day of month */
s = read_int(s,2,&tm->tm_mday);
date++;
} else if ( *fmt == 'm' ) {
s = read_int(s,2,&tm->tm_mon);
date++;
tm->tm_mon--;
} else if ( *fmt == 'y' ) {
s = read_int(s,2,&tm->tm_year);
date++;
tm->tm_year += 1900;
} else if ( *fmt == 'Y' ) {
s = read_int(s,4,&tm->tm_year);
date++;
/* tm->tm_year -= 1900; */
/* HOE tm->tm_year %= 100; */
} else if ( *fmt == 'j' ) {
s = read_int(s,3,&tm->tm_yday);
tm->tm_yday--;
date++;
yday++;
} else if ( *fmt == 'H' ) {
s = read_int(s,2,&tm->tm_hour);
} else if ( *fmt == 'M' ) {
s = read_int(s,2,&tm->tm_min);
} else if ( *fmt == 'S' ) {
s = read_int(s,2,&tm->tm_sec);
}
fmt++;
}
/* if (!yday && date) { */
if (date) {
/*
tm->tm_yday = 0;
for(i=0;i<tm->tm_mon;i++) {
tm->tm_yday += mndday[i] + (i==1 && (gdysize(tm->tm_year)>365));
}
tm->tm_yday += tm->tm_mday-1;
*/
if (yday) {
if ( tm->tm_yday < 0 || tm->tm_yday > gdysize(tm->tm_year)) {
int_error("illegal day of year",NO_CARET);
return(NULL);
}
} else {
if ( tm->tm_mon < 0 || tm->tm_mon > 11 ) {
int_error("illegal month",NO_CARET);
return(NULL);
}
if ( tm->tm_mday < 1 || tm->tm_mday > mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year)>365)) ) {
int_error("illegal day of month",NO_CARET);
return(NULL);
}
}
}
if ( tm->tm_hour < 0 || tm->tm_hour > 24 ) {
int_error("illegal hour",NO_CARET);
return(NULL);
}
if ( tm->tm_min < 0 || tm->tm_min > 60 ) {
int_error("illegal minute",NO_CARET);
return(NULL);
}
if ( tm->tm_sec < 0 || tm->tm_sec > 60 ) {
int_error("illegal second",NO_CARET);
return(NULL);
}
return(s);
}
static char *
read_int(s,nr,d)
char *s;
int nr, *d;
{
char num[8];
int i;
i = 0;
while(i<nr) {
if( *s >= '0' && *s <= '9' ) {
num[i++] = *s++;
} else {
break;
}
}
num[i] = '\0';
sscanf(num,"%d",d);
return(s);
}
int
gstrftime(s,bsz,fmt,clock)
char *s;
int bsz;
char *fmt;
double clock;
{
int xstrftime();
int days;
time_t cl;
struct tm tm;
struct tm *xtm;
ggmtime(&tm,clock);
/* weekday, 0 = sunday */
cl = 0;
xtm = gmtime(&cl);
/* antall dager */
days = (int) (clock+SEC_OFFS_SYS)/DAY_SEC;
/* weekrest */
days %= 7;
if ( days < 0 ) days += 7;
tm.tm_wday = (xtm->tm_wday+days)%7;
#if 0
if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone)+1)))
strcpy(tm.tm_zone,xtm->tm_zone);
/* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
#endif
return(xstrftime(s,bsz,fmt,&tm));
}
int
xstrftime(str,bsz,fmt,tm)
char *str;
int bsz;
char *fmt;
struct tm *tm;
{
int l;
char *p, *s;
p = fmt;
s = str;
memset(s,'\0',bsz+1);
l=0;
while (*p != '\0') {
if (*p != '%') {
if ( l >= bsz ) return(0);
*s++ = *p++;
l++;
} else {
p++;
if ( *p == '%' ) {
if ( l >= bsz ) return(0);
*s = '%';
} else if ( *p == 'a' ) {
if ((l+strlen(abbrev_day_names[tm->tm_wday])) > bsz ) return(0);
sprintf(s,"%s",abbrev_day_names[tm->tm_wday]);
} else if ( *p == 'A' ) {
if(l+strlen(full_day_names[tm->tm_wday]) > bsz) return(0);
sprintf(s,"%s",full_day_names[tm->tm_wday]);
} else if ( *p == 'b' || *p == 'h' ) {
if(l+strlen(abbrev_month_names[tm->tm_mon])> bsz) return(0);
sprintf(s,"%s",abbrev_month_names[tm->tm_mon]);
} else if ( *p == 'B' ) {
if(l+strlen(full_month_names[tm->tm_mon]) > bsz) return(0);
sprintf(s,"%s",full_month_names[tm->tm_mon]);
} else if ( *p == 'c' ) {
if (!xstrftime(s,bsz-l,"%x %X",tm)) {
return(0);
}
#if 0
} else if ( *p == 'C' ) {
if (!xstrftime(s,bsz-l,dtc->ldate_format,tm)) {
return(0);
}
#endif
} else if ( *p == 'd' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_mday);
} else if ( *p == 'D' ) {
if (!xstrftime(s,bsz-l,"%m/%d/%y",tm)) {
return(0);
}
} else if ( *p == 'e' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%2d",tm->tm_mday);
} else if ( *p == 'H' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_hour);
} else if ( *p == 'I' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_hour%12);
} else if ( *p == 'j' ) {
if ( bsz - l < 3 ) return(0);
sprintf(s,"%03d",tm->tm_yday+1);
} else if ( *p == 'k' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%2d",tm->tm_hour);
} else if ( *p == 'l' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%2d",tm->tm_hour%12);
} else if ( *p == 'm' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_mon+1);
} else if ( *p == 'M' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_min);
} else if ( *p == 'n' ) {
if ( bsz >= l ) return(0);
*s = '\n';
} else if ( *p == 'p' ) {
if(l+strlen((tm->tm_hour<12)?"am":"pm") > bsz) return(0);
sprintf(s,"%s",(tm->tm_hour<12)?"am":"pm");
} else if ( *p == 'r' ) {
if (!xstrftime(s,bsz-l,"%I:%M:%S %p",tm)) {
return(0);
}
} else if ( *p == 'R' ) {
if (!xstrftime(s,bsz-l,"%H:%M",tm)) {
return(0);
}
} else if ( *p == 'S' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_sec);
} else if ( *p == 't' ) {
if ( bsz >= l ) return(0);
*s = '\t';
} else if ( *p == 'T' ) {
if (!xstrftime(s,bsz-l,"%H:%M:%S",tm)) {
return(0);
}
} else if ( *p == 'W' ) { /* mon 1 day of week */
int week, bw;
if ( bsz - l < 2 ) return(0);
if ( tm->tm_yday <= tm->tm_wday ) {
week = 1;
if ( (tm->tm_mday - tm->tm_yday) > 4 ) {
week = 52;
}
if ( tm->tm_yday == tm->tm_wday && tm->tm_wday == 0 ) week = 52;
} else {
bw = tm->tm_yday - tm->tm_wday; /* sun prev week */
if ( tm->tm_wday > 0 ) bw += 7; /* sun end of week */
week = (int) bw/7;
if ( (bw%7) > 2 ) { /* jan 1 is before friday */
week++;
}
}
sprintf(s,"%02d",week);
} else if ( *p == 'U' ) { /* sun 1 day of week */
int week, bw;
if ( bsz - l < 2 ) return(0);
if ( tm->tm_yday <= tm->tm_wday ) {
week = 1;
if ( (tm->tm_mday - tm->tm_yday) > 4 ) {
week = 52;
}
} else {
bw = tm->tm_yday - tm->tm_wday-1; /* sat prev week */
if ( tm->tm_wday >= 0 ) bw += 7; /* sat end of week */
week = (int) bw/7;
if ( (bw%7) > 1 ) { /* jan 1 is before friday */
week++;
}
}
sprintf(s,"%02d",week);
} else if ( *p == 'w' ) { /* day of week, sun=0 */
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_wday);
#if 0
} else if ( *p == 'x' ) { /* locales date format */
if (!xstrftime(s,bsz-l,dtc->sdate_format,tm)) {
return(0);
}
} else if ( *p == 'X' ) { /* locales time format */
if (!xstrftime(s,bsz-l,dtc->time_format,tm)) {
return(0);
}
#endif
} else if ( *p == 'y' ) {
if ( bsz - l < 2 ) return(0);
sprintf(s,"%02d",tm->tm_year%100);
} else if ( *p == 'Y' ) {
if ( bsz - l < 4 ) return(0);
sprintf(s,"%04d",tm->tm_year);
#if 0
} else if ( *p == 'Z' ) {
if ( bsz - l < strlen(tm->tm_zone) ) return(0);
sprintf(s,"%s",tm->tm_zone);
#endif
}
p++;
while ( *s != '\0' ) {
s++;
l++;
}
}
}
return(l);
}
/* time_t */
double
gtimegm(tm)
struct tm *tm;
{
register int i;
/* returns sec from year ZERO_YEAR, defined in plot.h */
double dsec;
dsec = 0;
if ( tm->tm_year < ZERO_YEAR ) {
for(i=tm->tm_year;i<ZERO_YEAR;i++) {
dsec -= (double) gdysize(i);
}
} else {
for(i=ZERO_YEAR;i<tm->tm_year;i++) {
dsec += (double) gdysize(i);
}
}
if ( tm->tm_mday > 0 ) {
for (i=0;i<tm->tm_mon;i++) {
dsec += (double) mndday[i] + (i==1 && (gdysize(tm->tm_year)>365));
}
dsec += (double) tm->tm_mday-1;
} else {
dsec += (double) tm->tm_yday;
}
dsec *= (double) 24;
dsec += tm->tm_hour;
dsec *= 60.0;
dsec += tm->tm_min;
dsec *= 60.0;
dsec += tm->tm_sec;
return(dsec);
}
int
ggmtime(tm,clock)
struct tm *tm;
/* time_t clock; */
double clock;
{
/* clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */
int i, days;
tm->tm_year = ZERO_YEAR;
tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
if ( clock < 0 ) {
while ( clock < 0 ) {
tm->tm_year --;
clock += gdysize(tm->tm_year)*DAY_SEC; /* 24*3600 */
}
} else {
while ( clock >= (gdysize(tm->tm_year)*DAY_SEC) ) {
clock -= gdysize(tm->tm_year)*DAY_SEC;
tm->tm_year ++;
}
}
tm->tm_yday = (int)clock/DAY_SEC;
clock -= tm->tm_yday*DAY_SEC;
tm->tm_hour = (int)clock/3600;
clock -= tm->tm_hour*3600;
tm->tm_min = (int)clock/60;
clock -= tm->tm_min*60;
tm->tm_sec = (int)clock;
days = tm->tm_yday;
while ( days >= (i = mndday[tm->tm_mon] + (tm->tm_mon==1 && (gdysize(tm->tm_year)>365)))) {
days -= i;
tm->tm_mon ++;
}
tm->tm_mday = days+1;
return(0);
}
static void
parse_esc(instr)
char *instr;
{
char *s=instr, *t=instr;
/* the string will always get shorter, so we can do the
* conversion in situ
*/
while (*s != '\0' ) {
if ( *s == '\\' ) {
s++;
if ( *s == '\\' ) {
*t++ = '\\';
s++;
} else if ( *s == 'n' ) {
*t++ = '\n';
s++;
} else if ( *s == 'r' ) {
*t++ = '\r';
s++;
} else if ( *s == 't' ) {
*t++ = '\t';
s++;
} else if ( *s >= '0' && *s <= '7' ) {
int i,n;
if ( sscanf(s,"%o%n",&i, &n) > 0 ) {
*t++ = i;
s+=n;
} else {
/* int_error("illegal octal number ", c_token); */
*t++ = '\\';
*t++ = *s++;
}
}
} else {
*t++ = *s++;
}
}
*t = '\0';
}